home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-08-31 | 24.0 KB | 567 lines | [TEXT/CCL ] |
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;; Copyright 1987, 1988, 1989, 1990 by Ruben Kleiman for Apple Computer, Inc.
- ;;; Advanced Technology Group
- ;;;
-
- ;;; ADSP AppleTalk protocol Server Subsystem
-
- ;;; INSTRUCTIONS:
- ;;;
- ;;; Consult SAMPLE-SESSION.TXT file for an example of how to use
- ;;; the system at the highest level (assumes use of SERVER and EVENTS).
- ;;;
-
- (in-package :network :use '(ccl system lisp))
-
-
- ;;; Are we monitoring network events?
- ;;;
- (defvar *monitoring* t)
-
- (eval-when (load eval compile)
- (require :traps)
- (require :network-defs) ; needed record definitions (don't compile them!)
- (require :driver) ; the generic driver objects
- (require :NBP) ; this code handles the NBP protocol objects
- (require :server)) ; the generic server objects
-
-
- ;;; The ADSP Server uses these three types of objects:
- ;;; 1) *nbp-driver* ::= this is used for socket registration on the AppleTalk network--defined in NBP.Lisp
- ;;; 2) *adsp-stream* ::= used to write and read to/from a remote ADSP client or server
- ;;; 3) *adsp-server* ::= used by server node to listen for requests from remote ADSP clients
-
- ;;; You can perform any of the Common Lisp stream io calls on *adsp-stream*
- ;;; (currently, only string-tyo and string-tyi are supported).
-
- ;;; You use a *adsp-server* object if you develop a server which you want
- ;;; remote clients to access. This server can listen for connection requests from remote clients.
- ;;; Using turn-server-on and turn-server-off, however, you need never be aware of these objects
- ;;; (see generic-server.lisp).
-
- ;;; The *nbp-driver* and *adsp-driver* object instances are transparent to you. They are
- ;;; responsible for running the Macintosh .NBP & .DSP drivers.
-
-
- (defun report-adsp-error (ioResult)
- (or (= ioResult 0) ; Completed without error
- (= ioResult 1) ; Call did not complete (yet)
- (format t
- (case ioResult
- (-1280 "~%ADSP Bad connection refNum (~a)")
- (-1279 "~%ADSP Control call was aborted (~a)")
- (-1278 "~%ADSP Bad connection state for this operation (~a)")
- (-1277 "~%ADSP Open connection request failed or denied (~a)")
- (-1276 "~%ADSP Attention message data too long (~a)")
- (-1275 "~%ADSP Read terminated by forward reset (~a)")
- (OTHERWISE "~%ADSP Unknown error (~a)"))
- ioResult)))
-
- ;;; -------------------------------------------------------------------------------------------
- ;;; ADSP Driver Definitions
-
- (defobject *adsp-driver* *driver*)
-
- (defvar *the-adsp-driver* nil)
-
- (defun check-adsp-driver ()
- (or *the-adsp-driver*
- (setq *the-adsp-driver* (oneOf *adsp-driver* :driver-name ".DSP")))
- (or (ask *the-adsp-driver* driver-open-p)
- (ask *the-adsp-driver* (stream-open))))
-
- (defun adsp-driver-refNum ()
- (if (and *the-adsp-driver*
- (ask *the-adsp-driver* driver-open-p))
- (%get-word (ask *the-adsp-driver* driver-pb) $ioRefNum)
- (error "ADSP driver not open!")))
-
- (defun init-adsp ()
- (allow-local-loopback)
- (check-adsp-driver))
-
- ;;; -------------------------------------------------------------------------------------------
- ;;; *ADSP-STREAM* DEFINITIONS
-
- ;;; Allows us to recognize *adsp-stream* as a *stream*, although most (if not all)
- ;;; of the default stream methods are overriden here...
- (defobject *adsp-stream* *stream*)
-
- (defobfun (exist *adsp-stream*) (init-list)
- (usual-exist init-list)
- ;; some of the following are redundant, but worth keeping here until thoroughly debugged...
- (have 'input-buffer nil)
- (have 'input-count 0)
- (have 'next-input 0)
- (have 'output-buffer nil)
- (have 'output-count 0)
- (have 'service-name (getf init-list :service-name "unknown"))
- (have 'service-type (getf init-list :service-type "unknown"))
- (have 'stream-open-p nil)
- (have 'DriverRefNum nil)
- (have 'localSocket nil)
- (have 'ConnRefNum nil)
- (have 'driver-pb (_NewPtr :errchk :d0 $dspPBSize :a0)) ; the driver control block
- (have 'ccbPtr (make-record :TRCCB))) ; the ADSP connection control block
-
- (defobfun (driver-control *adsp-stream*) (code)
- "Handles driver control traps for ADSP streams"
- ;; The driver must be open!
- (%put-word driver-pb code $csCode)
- (_Control :a0 driver-pb))
-
- (defobfun (stream-open *adsp-stream*) (&optional remoteName remoteType &key (request-connection t))
- "Create, initialize, and open a connection end"
- (declare (object-variable DriverRefNum LOCALSOCKET CONNREFNUM SERVICE-NAME
- SERVICE-TYPE STREAM-OPEN-P))
- (setq DriverRefNum (adsp-driver-refNum))
- (initialize) ; Initialize queues and connection
- (setq LocalSocket (rref driver-pb DSPParamBlock.localSocket))
- (setq ConnRefNum (rref driver-pb DSPParamBlock.ccbRefNum))
- (setq service-name remoteName)
- (setq service-type remoteType)
-
- (and request-connection
- (request-connection remoteName remoteType)) ; connect to remote node
-
- (setq stream-open-p t)
- (and *monitoring* (format t "~%adsp stream opened on ~a" (self))))
-
- (defobfun (initialize *adsp-stream*) (&optional (qSize $StdQSize))
- "Initializes an ADSP stream object"
- (declare (object-variable DRIVERREFNUM CCBPTR))
- (check-adsp-driver)
- (rset driver-pb DSPParamBlock.ioVRefNum DriverRefNum)
- (rset driver-pb DSPParamBlock.ioCRefNum DriverRefNum)
- (rset driver-pb DSPParamBlock.ccbPtr ccbPtr)
- (rset driver-pb DSPParamBlock.userRoutine nil)
- (rset driver-pb DSPParamBlock.sendQSize qSize)
- (rset driver-pb DSPParamBlock.sendQueue (_NewPtr :errchk :d0 qSize :a0))
- (rset driver-pb DSPParamBlock.recvQSize qSize)
- (rset driver-pb DSPParamBlock.recvQueue (_NewPtr :errchk :d0 qSize :a0))
- (rset driver-pb DSPParamBlock.attnPtr (_NewPtr :errchk :d0 $attnBufSize :a0))
- (rset driver-pb DSPParamBlock.remoteAddress 0)
- (rset driver-pb DSPParamBlock.localSocket 0)
- (driver-control $dspInit)
- (report-adsp-error (%get-signed-word driver-pb $ioResult))
- (and *monitoring* (format t "~%adsp stream initialized on ~a" (self))))
-
- (defobfun (request-connection *adsp-stream*) (remoteName remoteType)
- (declare (object-variable DRIVERREFNUM CONNREFNUM))
- (check-adsp-driver)
-
- ;; Get internet address of remote node socket
- (multiple-value-bind (succeeded remoteAddress)
- (NBP-lookup remoteName remoteType)
- (if (not succeeded)
- (error "Could not find ~a server ~a" remoteName remoteType))
-
- ;; Request connection with remote node socket
- (rset driver-pb DSPParamBlock.csCode $dspOpen)
- (rset driver-pb DSPParamBlock.ioVRefNum DriverRefNum)
- (rset driver-pb DSPParamBlock.ioCRefNum DriverRefNum)
- (rset driver-pb DSPParamBlock.ccbRefNum ConnRefNum)
- (rset driver-pb DSPParamBlock.filterAddress 0)
- (rset driver-pb DSPParamBlock.ocMode $ocRequest)
- (rset driver-pb DSPParamBlock.ocInterval 50)
- (rset driver-pb DSPParamBlock.ocMaximum 20)
- (%put-full-long driver-pb remoteAddress 38)
- (_AControl :errchk :a0 driver-pb) ; asynch control call
- (report-adsp-error (%get-signed-word driver-pb $ioResult))
- (and *monitoring* (format t "~%adsp stream connection requested on ~a" (self)))))
-
- (defobfun (stream-close *adsp-stream*) ()
- "Closes the ADSP stream"
- (declare (object-variable CCBPTR STREAM-OPEN-P))
- (check-adsp-driver)
-
- (remove-connection)
-
- ;; Get rid of any allocated Mac heap storage
- (when (zone-pointerp (rref driver-pb DSPParamBlock.sendQueue))
- (_DisposPtr :errchk :a0 (rref driver-pb DSPParamBlock.sendQueue))
- (rset driver-pb DSPParamBlock.sendQueue 0))
- (when (zone-pointerp (rref driver-pb DSPParamBlock.recvQueue))
- (_DisposPtr :errchk :a0 (rref driver-pb DSPParamBlock.recvQueue))
- (rset driver-pb DSPParamBlock.recvQueue 0))
- (when (zone-pointerp (rref driver-pb DSPParamBlock.attnPtr))
- (_DisposPtr :errchk :a0 (rref driver-pb DSPParamBlock.attnPtr))
- (rset driver-pb DSPParamBlock.attnPtr 0))
- (when (zone-pointerp ccbPtr)
- (dispose-record ccbPtr)
- (setq ccbPtr nil))
- (when (zone-pointerp (rref driver-pb DSPParamBlock.remoteAddress))
- (_DisposPtr :errchk :a0 (rref driver-pb DSPParamBlock.remoteAddress))
- (rset driver-pb DSPParamBlock.remoteAddress 0))
- (when (zone-pointerp (rref driver-pb DSPParamBlock.filterAddress))
- (_DisposPtr :errchk :a0 (rref driver-pb DSPParamBlock.filterAddress))
- (rset driver-pb DSPParamBlock.filterAddress 0))
- (when (zone-pointerp driver-pb)
- (_DisposPtr :errchk :a0 driver-pb)
- (setq driver-pb nil))
- (setq stream-open-p nil)
- (and *monitoring* (format t "~%adsp stream closed on ~a" (self))))
-
- (defobfun (remove-connection *adsp-stream*) (&optional abort-p)
- "Unallocate ADSP stream io queues and terminate adsp connection"
- (declare (object-variable DRIVERREFNUM CONNREFNUM))
- (check-adsp-driver)
- (rset driver-pb DSPParamBlock.ioCRefNum DriverRefNum)
- (rset driver-pb DSPParamBlock.ccbRefNum ConnRefNum)
- (rset driver-pb DSPParamBlock.abort (or abort-p 0))
- (driver-control $dspRemove)
- (report-adsp-error (%get-signed-word driver-pb $ioResult))
- (and *monitoring* (format t "~%adsp stream connection removed on ~a" (Self))))
-
- (defobfun (accept-connection *adsp-stream*)
- (remoteCID remoteAddress sendSeq sendWindow attnSendSeq)
- (declare (object-variable DRIVERREFNUM CONNREFNUM))
- (check-adsp-driver)
- (rset driver-pb DSPParamBlock.ioCRefNum DriverRefNum)
- (rset driver-pb DSPParamBlock.ccbRefNum ConnRefNum)
- (rset driver-pb DSPParamBlock.remoteCID remoteCID)
- (rset driver-pb DSPParamBlock.sendSeq sendSeq)
- (rset driver-pb DSPParamBlock.sendWindow sendWindow)
- (rset driver-pb DSPParamBlock.attnSendSeq attnSendSeq)
- (rset driver-pb DSPParamBlock.filterAddress 0)
- (rset driver-pb DSPParamBlock.ocMode $ocAccept)
- (rset driver-pb DSPParamBlock.ocInterval 50)
- (rset driver-pb DSPParamBlock.ocMaximum 20)
- (%put-full-long driver-pb remoteAddress 38)
- (driver-control $dspOpen)
- (report-adsp-error (%get-signed-word driver-pb $ioResult))
- (and *monitoring* (format t "~%adsp stream connection accepted on ~a" (self)))
- (self)) ; must return SELF
-
- (defobfun (status *adsp-stream*) ()
- (declare (object-variable DRIVERREFNUM CONNREFNUM))
- (rset driver-pb :DSPParamBlock.ioCRefNum DriverRefNum)
- (rset driver-pb :DSPParamBlock.ccbRefNum ConnRefNum)
- (driver-control $dspStatus)
- (report-adsp-error (%get-signed-word driver-pb $ioResult))
- (values (nth (1- (rref (rref driver-pb DSPParamBlock.statusCCB) TRCCB.state))
- '(listening passive opening open closing closed))
- (rref driver-pb DSPParamBlock.sendQPending)
- (rref driver-pb DSPParamBlock.sendQFree)
- (rref driver-pb DSPParamBlock.recvQPending)
- (rref driver-pb DSPParamBlock.recvQFree)))
-
- (defobfun (stream-eofp *adsp-stream*) ()
- (not (stream-listen)))
-
- (defobfun (stream-listen *adsp-stream*) ()
- (declare (object-variable next-input input-count))
- (or (< next-input input-count)
- (multiple-value-bind (state send-count send-free received-count receive-free)
- (status)
- (declare (ignore receive-free send-free send-count state))
- (> received-count 0))))
-
- (defobfun (stream-tyi *adsp-stream*) ()
- (declare (object-variable NEXT-INPUT INPUT-COUNT INPUT-BUFFER))
- (cond ((< next-input input-count)
- (aref input-buffer (1- (incf next-input)))) ; maybe copy?
- (t (string-receive)
- (stream-tyi))))
-
- (defobfun (stream-tyo *adsp-stream*) (char)
- (declare (object-variable OUTPUT-BUFFER OUTPUT-COUNT))
- (setq output-buffer
- (concatenate 'simple-string
- output-buffer
- (string char)))
- (if (> (incf output-count) 255) ; incf is messed
- (stream-force-output)))
-
- (defobfun (stream-force-output *adsp-stream*) ()
- (declare (object-variable OUTPUT-BUFFER DRIVERREFNUM CONNREFNUM OUTPUT-COUNT))
- (with-pstrs ((data output-buffer)) ; temporary ptr should work because I'm sending immediate (I hope)
- (rset driver-pb DSPParamBlock.ioCRefNum DriverRefNum)
- (rset driver-pb DSPParamBlock.ccbRefNum ConnRefNum)
- (rset driver-pb DSPParamBlock.reqCount output-count)
- (rset driver-pb DSPParamBlock.dataPtr (ccl::%inc-ptr data 1)) ; jump over Pascal string header
- (rset driver-pb DSPParamBlock.eom 1)
- (rset driver-pb DSPParamBlock.flush 1)
- (driver-control $dspWrite))
- (report-adsp-error (%get-signed-word driver-pb $ioResult))
- (setq output-count 0)
- (setq output-buffer "")
- (- (rref driver-pb DSPParamBlock.actCount) 1))
-
- (defobfun (stream-fresh-line *adsp-stream*) ()
- (stream-tyo #\NewLine))
-
- (defobfun (stream-untyi *adsp-stream*) (char)
- (declare (object-variable INPUT-COUNT INPUT-BUFFER))
- (incf input-count)
- (setq input-buffer
- (concatenate 'simple-string (string char) input-buffer))
- char)
-
- (defobfun (stream-clear-input *adsp-stream*) ()
- (declare (object-variable INPUT-BUFFER))
- (setq input-buffer nil))
-
- (defobfun (stream-abort *adsp-stream*) ()
- (stream-close))
-
- (defobfun (string-receive *adsp-stream*) ()
- (declare (object-variable NEXT-INPUT INPUT-COUNT INPUT-BUFFER))
- (do ((string-read (coerce (get-adsp-string) 'simple-string)
- (concatenate 'simple-string string-read (get-adsp-string))))
- ((or (= 1 (rref driver-pb DSPParamBlock.eom))
- (stream-eofp))
- (setq next-input 0)
- (setq input-count (length string-read))
- (setq input-buffer string-read))))
-
- (defobfun (get-adsp-string *adsp-stream*) ()
- (declare (object-variable DRIVERREFNUM CONNREFNUM))
- (if (stream-eofp)
- ""
- (%stack-block ((dataPtr $StdQSize))
- (rset driver-pb DSPParamBlock.ioCRefNum DriverRefNum)
- (rset driver-pb DSPParamBlock.ccbRefNum ConnRefNum)
- (rset driver-pb DSPParamBlock.reqCount $StdQSize)
- (rset driver-pb DSPParamBlock.dataPtr dataPtr)
- (driver-control $dspRead)
- (report-adsp-error (%get-signed-word driver-pb $ioResult))
- (ccl::%str-from-ptr (rref driver-pb DSPParamBlock.dataPtr)
- (rref driver-pb DSPParamBlock.actCount)))))
-
- (defobfun (string-read-immediate *adsp-stream*) ()
- (do ((string-read (coerce (get-adsp-string) 'simple-string)
- (concatenate 'simple-string string-read (get-adsp-string))))
- ((or (= 1 (rref driver-pb DSPParamBlock.eom))
- (stream-eofp))
- string-read)))
-
- ;;; -------------------------------------------------------------------------------------------
- ;;; *adsp-server* DEFINITIONS
-
- ;;; The adsp server is initiated through a stream-open. The server can be activated and deactivated
- ;;; by sending it a server-on and server-off message, respectively. The server can
- ;;; be disposed through the remove-server message.
-
- (defobject *adsp-server* *adsp-stream* *server*)
-
- (defobfun (stream-open *adsp-server*) ()
- "Open and initialize the ADSP server"
- (declare (object-variable STREAM-OPEN-P DRIVERREFNUM))
- (setq stream-open-p t)
- (setq DriverRefNum (adsp-driver-refNum))
- (initialize)
- (and *monitoring* (format t "~%adsp server stream opened on ~a" (self))))
-
- (defobfun (initialize *adsp-server*) ()
- "Create and initialize an ADSP stream--without send-rcv-attn buffers!"
- (declare (object-variable DRIVERREFNUM CCBPTR LOCALSOCKET CONNREFNUM))
- (check-adsp-driver)
- (rset driver-pb DSPParamBlock.ioVRefNum DriverRefNum)
- (rset driver-pb DSPParamBlock.ioCRefNum DriverRefNum)
- (rset driver-pb DSPParamBlock.ccbPtr ccbPtr)
- (rset driver-pb DSPParamBlock.userRoutine nil)
- (rset driver-pb DSPParamBlock.localSocket 0)
- (driver-control $dspCLInit)
- (report-adsp-error (%get-signed-word driver-pb $ioResult))
- (setq localSocket (rref driver-pb DSPParamBlock.localSocket))
- (setq ConnRefNum (rref driver-pb DSPParamBlock.ccbRefNum))
- (and *monitoring* (format t "~%adsp server initialized on ~a" (self))))
-
-
- (defobfun (remove-connection *adsp-server*) (&optional abort-p)
- "Terminate and dispose of ADSP server"
- (declare (object-variable DRIVERREFNUM CONNREFNUM))
- (check-adsp-driver)
- (rset driver-pb DSPParamBlock.ioCRefNum DriverRefNum)
- (rset driver-pb DSPParamBlock.ccbRefNum ConnRefNum)
- (rset driver-pb DSPParamBlock.abort (or abort-p 0))
- (driver-control $dspCLRemove)
- (report-adsp-error (%get-signed-word driver-pb $ioResult))
- (and *monitoring* (format t "~%adsp server connection removed on ~a" (self))))
-
- (defobfun (server-on *adsp-server*) ()
- "Register server & listen for remote requests"
- (declare (object-variable NAME TYPE LOCALSOCKET REGISTERED-P))
- (check-adsp-driver)
- (NBP-register name type localSocket)
- (setq registered-p t)
- (server-listen))
-
- (defobfun (server-listen *adsp-server*) ()
- "Listen for a remote request"
- (rset driver-pb DSPParamBlock.filterAddress 0)
- (rset driver-pb DSPParamBlock.localCID 0)
- (rset driver-pb DSPParamBlock.remoteCID 0)
- (%put-word driver-pb $dspCLListen $csCode)
- (_AControl :errchk :a0 driver-pb) ; asynch control call
- (report-adsp-error (%get-signed-word driver-pb $ioResult)))
-
- (defobfun (server-off *adsp-server*) ()
- (declare (object-variable NAME TYPE REGISTERED-P))
- "Unregister server & stop listening for remote requests"
- (NBP-unregister name type)
- (setq registered-p nil)
- (stream-close))
-
- (pushnew (list :adsp *adsp-server*) *supported-server-media*)
-
- ;;; If we have a successful completion, then create a client stream, accept the request,
- ;;; and queue the stream on *new-clients*
- ;;; Accept client code is going to be a bit slow, so it might require
- ;;; "long" waits for other requestors: if it becomes a problem, either
- ;;; (1) the code may be queued for higher level execution, or
- ;;; (2) an all-purpose accept-communication *adsp-stream* object may be
- ;;; kept around just for accepting connections, deferring creation of
- ;;; the new-client stream to higher level code
-
- ;;; Since (eval-when (load) ...) does not work per CL at this time,
- ;;; the adsp medium is defined at load time by evaluating (service-form):
-
- (defun service-form ()
- '(define-server-medium :ADSP
- (ON-CLIENT-REQUEST
- (cond (deny-connection! ; deny connection and listen for other requests
- (deny-connection))
- (t ;; create a client stream and accept communications for it
- (let ((new-client (oneOf *adsp-stream*))
- (remoteCID (rref driver-pb DSPParamBlock.remoteCID))
- (remoteAddress (rref driver-pb DSPParamBlock.remoteAddress))
- (sendSeq (rref driver-pb DSPParamBlock.sendSeq))
- (sendWindow (rref driver-pb DSPParamBlock.sendWindow))
- (attnSendSeq (rref driver-pb DSPParamBlock.attnSendSeq))
- (the-name name) ; lexically bind name & type
- (the-type type))
- (ask new-client
- (stream-open the-name the-type :request-connection nil))
- (and *monitoring* (format t "~%About to accept conn")) ; SHOULD GET RID OF THIS!!!
- (ask new-client
- (accept-connection remoteCID remoteAddress sendSeq sendWindow attnSendSeq))
- new-client))))
- (ON-SERVER-ERROR (error-code)
- (cerror "RESET ~a SERVER ~a & CONTINUE ..." "~a server ~a error ~a" type name error-code))))
-
- (eval (service-form))
-
- (defobfun (deny-connection *adsp-server*) ()
- (check-adsp-driver)
- (driver-control $dspCLDeny)
- (report-adsp-error (%get-signed-word driver-pb $ioResult))
- (and *monitoring* (format t "~%adsp server connection denied on ~a" (self)))
- NIL) ; must return NIL
-
- (defun initDrivers ()
- (check-nbp-driver) ; force load .NBP
- (check-adsp-driver) ; force load .DSP
- (allow-local-loopback)) ; allow server & client to coexist in machine
-
-
- (push :adsp *features*)
-
- #|
-
- ;;; -----------------------------------------------------------------------------------------------
- ;;; AN EXAMPLE
- ;;; -----------------------------------------------------------------------------------------------
-
- ;;; INSTRUCTIONS:
-
- ;;; Execute ADSP-SERVER-EXAMPLE on one machine and then ADSP-CLIENT-EXAMPLE on another.
- ;;; Both machines must be connected through AppleTalk cable and the ADSP init must be
- ;;; inside the System Folder. Also, you should make sure that the CHOOSER shows
- ;;; that AppleTalk is active (if not, select it to be so).
-
- ;;; To load the ADSP protocol functions, just (require :ADSP)
-
- ;;; Now evaluate the ADSP-SERVER-EXAMPLE and ADSP-CLIENT-EXAMPLE functions in each
- ;;; machine, respectively. Then first evaluate ADSP-SERVER-EXAMPLE in Machine #1
- ;;; and then evaluate ADSP-CLIENT-EXAMPLE in Machine #2. Modify the code to do
- ;;; other sorts of things. For example, if you remove the
- ;;; turn-server-off instruction in ADSP-SERVER-EXAMPLE (Machine #1) you'll be able
- ;;; to evaluate ADSP-CLIENT-EXAMPLE more than once on Machine #2.
-
- ;;; WHAT THE EXAMPLE CODE DOES:
-
- ;;; A server in one machine listens for requests from any network node to print a string
- ;;; on the server's listener window. It includes the code for the client node that
- ;;; would send such a request. (Note: the client and server could be in the same node.)
-
-
-
- ;;; CODE FOR MACHINE #1 (THE SERVER PART):
-
- ;;; This server reads a message from clients and prints it on the local listener
- (defun ADSP-SERVER-EXAMPLE (&aux my-server-name my-server-type my-new-client)
-
- (setq my-server-name "a good listener window")
- (setq my-server-type "window printer")
-
- (server::turn-server-on :ADSP :name my-server-name :type my-server-type) ; you turn the server on
- (format t "~%SERVER> server turned on...")
-
- ;; THE SERVER LISTENER IS TURNED ON: IT MEANS THAT THE SERVER'S LISTENER IS LISTENING
- ;; IN THE BACKGROUND FOR REQUESTS FROM "CLIENTS" TO CONNECT TO IT AND USE ITS SERVICES.
- ;; THE CLIENT MAY BE ANYWHERE IN THE NETWORK (INCLUDING IN THE SAME MACHINE).
- ;; WHEN THE SERVER LISTENER HEARS A REQUEST, IT CREATES A STREAM WHICH IS DIRECTLY CONNECTED
- ;; TO THE CLIENT SO THAT YOU MAY TALK TO THE CLIENT THROUGH IT. YOU PICK UP THE STREAM
- ;; USING THE GET-NEW-CLIENT CALL. IF THE CLIENT RETURNS NOTHING, THEN NO ONE CALLED YOU (TOO BAD).
- ;; OF COURSE, YOU WILL NOT NORMALLY LOOP LIKE THIS TO WAIT FOR A REQUEST... YOU
- ;; PRESUMABLY HAVE OTHER THINGS TO DO. (A FUTURE VERSION WILL ALLOW YOU TO WRITE THE
- ;; CODE THAT HANDLES REQUESTS FOR YOU WHEN A NEW CLIENT SHOWS UP WITHOUT YOUR
- ;; HAVING TO ACTIVELY LOOK FOR CLIENTS YOURSELF.)
-
- (format t "~%SERVER> waiting for client requests ...")
- (loop
- (format t ".")
- (setq my-new-client (server::get-new-client my-server-name my-server-type))
- (when my-new-client
- (return nil))
- )
- (format t "~%SERVER> ADSP server found a client...")
-
- (server::turn-server-off :ADSP my-server-name my-server-type)
- (format t "~%SERVER> ADSP server turned off...")
-
- ;; NOW YOU READ A STRING FROM YOUR CLIENT AND PRINT IT ON YOUR LISTENER WINDOW!
- (format t "~%~%SERVER>>>>>>> ~a~%~%" (ask my-new-client (string-tyi)))
-
- (ask my-new-client (stream-close))
- (format t "~%SERVER> ADSP stream removed..."))
-
-
-
- CODE FOR MACHINE #2 (THE CLIENT PART):
-
- ;;; This is an example of an ADSP client that will look in the network for an ADSP server
- ;;; called "my listener window" of type "window printer". The latter will accept a
- ;;; string from a client and will print it on the server's lisp listener window.
-
- ;;; The client just opens a stream to that server, sends a string to it, and closes the stream.
- (defun ADSP-CLIENT-EXAMPLE (&aux my-server-stream the-server-name the-server-type)
- "Example of an ADSP client"
-
- ;; THERE'S NOW A BETTER WAY OF DOING THIS USING SERVER::TURN-CLIENT-ON
- ;; AND SERVER::TURN-CLIENT-OFF. CHECK THOSE FUNCTIONS!
-
- (setq the-server-name "a good listener window")
- (setq the-server-type "window printer")
-
- ;; CREATE AN ADSP STREAM OBJECT WITH WHICH TO TALK TO THE SERVER
- (setq my-server-stream (oneOf *adsp-stream* ))
- (format t "~%CLIENT> an ADSP stream created...")
-
- ;; OPEN YOUR STREAM
- (ask my-server-stream (stream-open the-server-name the-server-type))
- (format t "~%CLIENT> an ADSP stream opened...")
-
- ;; SEND A STRING TO THE SERVER
- (ask my-server-stream (string-out "Hi there nice remote listener window!"))
- (format t "~%CLIENT> send Hi There message to LISTENER LISP server...")
-
- ;; CLOSE YOUR STREAM WHEN YOU ARE DONE WRITING TO THE SERVER
- (ask my-server-stream (stream-close))
- (format t "~%CLIENT> closed stream connection..."))
-
- |#
-
- (provide :adsp)